package io.github.ali.commons.variable;

import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;

import io.github.ali.commons.function.NAFunction;


/**
 * 基于Quartz定时触发动作
 * 
 * @author fuli
 * @date 2018年12月4日
 * @version 1.0.0
 */
public abstract class QuartzActionGenerator extends ActionExecuter{
	public static final String CONTEXT_ACTION = "action";
	private SchedulerFactory schedulerFactory;
	private Scheduler scheduler;
	private JobDetail jobDetail;
	public QuartzActionGenerator(NAFunction action) {
		super(action);
		schedulerFactory = new StdSchedulerFactory();
		JobDataMap jm=new JobDataMap();
		NAFunction jobAction = () -> triggerExecute();
		jm.put(CONTEXT_ACTION,jobAction);
		jobDetail=JobBuilder.newJob(ActionJob.class).setJobData(jm).build();
	}
	
	@Override
	protected void postStart() {
		try {
			if (scheduler == null || scheduler.isShutdown()) {
				scheduler = schedulerFactory.getScheduler();
				scheduler.start();
			}
			LOGGER.info("the {},{} begin run in {}!",this.getClass().getSimpleName(),name,scheduler.scheduleJob(jobDetail, buildTrigger()));
		} catch (SchedulerException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	protected void preStop() {
		try {
			if (scheduler != null && !scheduler.isShutdown()) {
				scheduler.shutdown();
			}
			scheduler = null;
		} catch (SchedulerException e) {
			throw new RuntimeException(e);
		}
	}

	abstract protected Trigger buildTrigger();
	
	public static class ActionJob implements Job{
		@Override
		public void execute(JobExecutionContext context) throws JobExecutionException {
			((NAFunction)context.getJobDetail().getJobDataMap().get(CONTEXT_ACTION)).apply();
		}
	}
}
